package com.zsrt.scott.listener;

import java.io.File;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.zsrt.scott.datasource.DriverManagerDataSource;

public class ContextLoaderListener implements ServletContextListener {
	
	
	private String path="";
	
	public static Connection connection;
	
	
	private Element root;
	
	
	
	
	public void  mapper(){
		
		//根据applicationContext.xml文件中的location配置所有的找到mapper文件
		String file =path+"/WEB-INF/classes/com/zsrt/scott/mapper/"+"StudentMapper.xml";
		
		
		parserMapperFile(file) ;
		
	}
	

	private void parserMapperFile(String file) {
		
		//1 根据传过来的路径  使用dom4j解析xml
		SAXReader reader = new SAXReader();  
		//读取文件 转换成Document  
		
		
		//? 需要写活 ?
		
		//获取项目的发布路径
		
		
		try {
			Document document = reader.read(file);
			
			System.out.println(document.getClass().getName());
			//拿到根节点 beans
			root = document.getRootElement();
			
			String namespace = root.attributeValue("namespace");
			System.out.println("namespace="+namespace);
			
			//生成接口StudentDao的实现类  用动态代理
			
			
			
			
			
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		
	}


	@Override
	public void contextInitialized(ServletContextEvent sc) {
		
		
		
		
		String contextPath= sc.getServletContext().getRealPath("/");
		
		path=contextPath;
		
		mapper();
		
		System.out.println(contextPath);
		
		System.out.println("启动监听器....");
		
		
		//要做什么事情?
		
		
		//怎么去读取配置文件中的东西 applicationContext.xml
		
		
		String dizhi = sc.getServletContext().getInitParameter("contextConfigLocation");
		
		System.out.println(dizhi);
		
		
		//解析文件  形成DriverManagerDataSource类的对象  用来连接数据库
		
		parserXmlFile(dizhi);
		
		
	}

	private void parserXmlFile(String dizhi) {
		try {
			//1 根据传过来的路径  使用dom4j解析xml
			SAXReader reader = new SAXReader();  
			//读取文件 转换成Document  
			
			
			//? 需要写活 ?
			
			//获取项目的发布路径
			
			
			Document document = reader.read(new File(path+"/WEB-INF/classes/"+dizhi));
			
			System.out.println(document.getClass().getName());
			//拿到根节点 beans
			root = document.getRootElement();
			
			
			List beanList = root.elements();
			
			for(Object obj: beanList){
				
				Element bean =(Element)obj;
				
				String val = bean.attributeValue("class");
				
				System.out.println("val="+val);
				
				//只处理1个数据库的情况 不涉及分布式的数据库
				if("com.zsrt.scott.datasource.DriverManagerDataSource".equals(val)){
					
					
					// 拿到包含连接数据库4个信息的对象
					DriverManagerDataSource dataSource = (DriverManagerDataSource)getConnectionObject(val);
					
					//根据包含连接数据库的4个信息的对象生成Connection
					connection =getDataBaseConnection(dataSource);
					
				}
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	

	/**
	 * 根据包含连接数据库的4个信息的对象生成Connection
	 * @param dataSource
	 * @return
	 */
	private Connection getDataBaseConnection(DriverManagerDataSource dataSource) {
		
		Connection cn=null;
		try {
			//jdbc连接数据库
			Class.forName(dataSource.getDriver());
			
			cn = DriverManager.getConnection(dataSource.getUrl(), dataSource.getUsername(), dataSource.getPassword());
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return cn;
	}

	/**
	 * 拿到包含连接数据库4个信息的对象
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "unused" })
	private Object getConnectionObject(String clazz) {
		
		//反射 并赋值
		Object dataSource = null;
		try {
			Class  clss = Class.forName(clazz);
			
			//生成类的对象
			
			dataSource = clss.newInstance();
			
			List beanList = root.elements();
			
			for(Object obj: beanList){
				
				Element bean =(Element)obj;
				
				String val = bean.attributeValue("class");
				
				System.out.println("val="+val);
				
				//只处理1个数据库的情况 不涉及分布式的数据库
				if("com.zsrt.scott.datasource.DriverManagerDataSource".equals(val)){
					
					//生成DriverManagerDataSource类的对象用来连接数据库
					
					
					List<Element> propertyList = bean.elements();
					
					System.out.println(propertyList.size());
					
					for(Element property :propertyList){
						
						//username
						String name = property.attributeValue("name");
						//root
						String value = property.attributeValue("value");
						
						//把字符串"root" 赋值给 DriverManagerDataSource类的对象的username
						
						Field[] fs = clss.getDeclaredFields();
						
						//循环类的属性  看那个属性的名字等于username 就把root的值赋值给username
						
						for(Field f: fs){
							
							String fn = f.getName();
							
							if(fn.equals(name)){
								
								f.setAccessible(true);
								f.set(dataSource, value);
							}
							
							
						}
						
						
						
					}
					
				}
				
			}
			
			System.out.println("dataSource="+dataSource);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return dataSource;
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("关闭监听器....");
	}

}
